package advice;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;

import java.util.Arrays;

public class CacheAdvice {

    /**
     * 前置通知 - 在目标方法执行之前执行
     */
    public void before(JoinPoint jp){

        Object[] args = jp.getArgs();
        System.out.println("目标方法的参数：" + Arrays.toString(args));

        Signature signature = jp.getSignature();
        System.out.println("目标方法的签名：" + signature);

        System.out.println("查询缓存~~");
    }

    /**
     * 最终通知方法 - 相当于是finally中的代码
     */
    public void after(){
        System.out.println("after~~");
    }

    /**
     * 返回后通知 - 在目标方法正常执行后执行
     *      只有在这个增强通知中可以获取目标方法的返回值，finally中的代码执行时，目标方法不一定是正常执行你的，所在在after中是五发获取返回值
     */
    public void afterReturning(Object res){
        System.out.println("afterReturning~~");

        System.out.println("目标方法正常执行完后的返回值： "+ res);
    }

    /**
     * 异常通知 - 在目标方法异常执行后执行
     *      只有这个增强通知中才可以获取到目标方法执行的异常
     */
    public void afterThrowing(Throwable err){
        System.out.println("afterThrowing~~");
        System.out.println("目标方法执行异常信息：" + err.getMessage());
    }

    /**
     * 环绕通知(必须接收ProceedingJoinPoint参数 + 必须设定Object返回)
     *  ProceedingJoinPoint 这个对象中封装了目标对象和目标对象的方法及其参数
     */
    public Object around(ProceedingJoinPoint pjp) {
        try {
            Object[] args = pjp.getArgs();
            System.out.println("环绕通知获取参数：" + Arrays.toString(args));
            Signature signature = pjp.getSignature();
            System.out.println("环绕通知获取签名：" + signature);

            System.out.println("around-before");

            String methodName = signature.getName();
            if (methodName.equals("delete")){
                args[0] = 5;
            }

            //执行目标方法
//            Object result = pjp.proceed();
            Object result = pjp.proceed(args); //将我们修改后的参数传递给目标方法

            System.out.println("around-afterReturning");

            return result;
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("around-afterThrowing");
        }finally {
            System.out.println("around-after");
        }
        return null;
    }
}